import React, { useEffect, useRef, useState, useCallback } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import {
  Box,
  Paper,
  Typography,
  IconButton,
  Tabs,
  Tab,
  Menu,
  MenuItem,
  Tooltip,
  Alert,
  CircularProgress,
  Button,
  Drawer,
  List,
  ListItem,
  ListItemText,
  Divider,
  Switch,
  FormControlLabel,
} from '@mui/material';
import {
  Add as AddIcon,
  Close as CloseIcon,
  Settings as SettingsIcon,
  Fullscreen as FullscreenIcon,
  FullscreenExit as FullscreenExitIcon,
  ContentCopy as CopyIcon,
  ContentPaste as PasteIcon,
  Refresh as RefreshIcon,
  MoreVert as MoreVertIcon,
  ViewSidebar as ViewSidebarIcon,
  Clear as ClearIcon,
} from '@mui/icons-material';
import { Terminal as XTerm } from 'xterm';
import { FitAddon } from 'xterm-addon-fit';
import { WebLinksAddon } from 'xterm-addon-web-links';
import { SearchAddon } from 'xterm-addon-search';
import { invoke } from '@tauri-apps/api/core';
import { listen } from '@tauri-apps/api/event';
import toast from 'react-hot-toast';

// Store
import { useAppStore } from '../store/appStore';

// Types
import type { Terminal as TerminalType, TerminalEvent } from '../types/ssh';

interface TabPanelProps {
  children?: React.ReactNode;
  index: number;
  value: number;
}

function TabPanel(props: TabPanelProps) {
  const { children, value, index, ...other } = props;

  return (
    <div
      role="tabpanel"
      hidden={value !== index}
      id={`terminal-tabpanel-${index}`}
      aria-labelledby={`terminal-tab-${index}`}
      style={{ height: '100%' }}
      {...other}
    >
      {value === index && children}
    </div>
  );
}

interface LogEntry {
  id: string;
  timestamp: Date;
  level: 'info' | 'warn' | 'error' | 'debug';
  message: string;
  source: 'connection' | 'terminal' | 'system';
}

const Terminal: React.FC = () => {
  const { connectionId } = useParams<{ connectionId?: string }>();
  const navigate = useNavigate();
  const {
    connections,
    activeConnections,
    addTerminal,
    updateTerminal,
    removeTerminal,
    getTerminalsByConnection,
    selectedTerminalId,
    setSelectedTerminalId,
    config,
  } = useAppStore();

  const [currentTab, setCurrentTab] = useState(0);
  const [isFullscreen, setIsFullscreen] = useState(false);
  const [contextMenu, setContextMenu] = useState<{
    mouseX: number;
    mouseY: number;
  } | null>(null);
  const [isLoading, setIsLoading] = useState(false);
  const [logPanelOpen, setLogPanelOpen] = useState<boolean>(false);
  const [logs, setLogs] = useState<LogEntry[]>([]);
  const [autoScroll, setAutoScroll] = useState<boolean>(true);


  // Terminal实例引用
  const terminalRefs = useRef<Map<string, XTerm>>(new Map());
  const fitAddonRefs = useRef<Map<string, FitAddon>>(new Map());
  const terminalContainerRefs = useRef<Map<string, HTMLDivElement>>(new Map());
  const logContainerRef = useRef<HTMLDivElement>(null);

  // 获取当前连接的终端列表
  const currentTerminals = connectionId ? getTerminalsByConnection(connectionId) : [];

  // 添加日志条目
  const addLog = useCallback((level: LogEntry['level'], message: string, source: LogEntry['source'] = 'system') => {
    const newLog: LogEntry = {
      id: `log_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
      timestamp: new Date(),
      level,
      message,
      source,
    };
    
    setLogs(prevLogs => {
      const updatedLogs = [...prevLogs, newLog];
      // 保持最多1000条日志
      if (updatedLogs.length > 1000) {
        return updatedLogs.slice(-1000);
      }
      return updatedLogs;
    });

    // 自动滚动到底部
    if (autoScroll && logContainerRef.current) {
      setTimeout(() => {
        if (logContainerRef.current) {
          logContainerRef.current.scrollTop = logContainerRef.current.scrollHeight;
        }
      }, 100);
    }
  }, [autoScroll]);

  // 清空日志
  const clearLogs = useCallback(() => {
    setLogs([]);
  }, []);

  // 格式化日志时间
  const formatLogTime = (timestamp: Date) => {
    return timestamp.toLocaleTimeString('zh-CN', {
      hour12: false,
      hour: '2-digit',
      minute: '2-digit',
      second: '2-digit',
      fractionalSecondDigits: 3,
    });
  };

  // 获取日志级别颜色
  const getLogLevelColor = (level: LogEntry['level']) => {
    switch (level) {
      case 'error': return '#f44336';
      case 'warn': return '#ff9800';
      case 'info': return '#2196f3';
      case 'debug': return '#9e9e9e';
      default: return '#000000';
    }
  };
  const currentConnection = connectionId ? connections.find(c => c.id === connectionId) : null;
  const activeConnection = connectionId ? activeConnections.find(ac => ac.id === connectionId) : null;

  // 创建新终端
  const createTerminal = useCallback(async (connId: string, command?: string) => {
    if (!connId) return;

    // 检查SSH连接是否存在且已建立
    const activeConnection = activeConnections.find(ac => ac.id === connId);
    if (!activeConnection) {
      addLog('error', '未找到活动的SSH连接，请先在连接管理页面建立SSH连接', 'terminal');
      toast.error('请先建立SSH连接');
      navigate('/connections');
      return;
    }

    if (activeConnection.status.status !== 'connected') {
      addLog('error', `SSH连接状态异常: ${activeConnection.status.status}，请重新连接`, 'terminal');
      toast.error('SSH连接未建立，请重新连接');
      navigate('/connections');
      return;
    }

    setIsLoading(true);
    addLog('info', `正在创建终端会话...${command ? ` 执行命令: ${command}` : ''}`, 'terminal');
    
    try {
      // 调用后端创建终端会话
      const terminalId = await invoke('create_terminal', {
          connectionId: connId,
          command: command || null,
        }) as string;

      addLog('info', `终端会话创建成功，ID: ${terminalId}`, 'terminal');

      const newTerminal: TerminalType = {
        id: terminalId,
        connection_id: connId,
        title: `Terminal ${currentTerminals.length + 1}`,
        status: { status: 'active' },
        size: { cols: 80, rows: 24 },
        created_at: new Date().toISOString(),
      };

      addTerminal(newTerminal);
      setSelectedTerminalId(newTerminal.id);
      
      // 切换到新创建的终端标签
      const newTabIndex = currentTerminals.length;
      setCurrentTab(newTabIndex);

      addLog('info', `终端会话创建成功: ${newTerminal.id}`, 'terminal');
      toast.success('终端会话已创建');
    } catch (error) {
      const errorMsg = error instanceof Error ? error.message : String(error);
      addLog('error', `创建终端失败: ${errorMsg}`, 'terminal');
      console.error('Failed to create terminal:', error);
      toast.error('创建终端失败: ' + errorMsg);
    } finally {
      setIsLoading(false);
    }
  }, [currentTerminals.length, addTerminal, setSelectedTerminalId, addLog, activeConnections, navigate]);

  // 关闭终端
  const closeTerminal = useCallback(async (terminalId: string) => {
    addLog('info', `正在关闭终端会话: ${terminalId}`, 'terminal');
    
    try {
      await invoke('close_terminal', { terminalId });
      
      // 清理终端实例
      const terminal = terminalRefs.current.get(terminalId);
      if (terminal) {
        terminal.dispose();
        terminalRefs.current.delete(terminalId);
        fitAddonRefs.current.delete(terminalId);
        terminalContainerRefs.current.delete(terminalId);
      }

      removeTerminal(terminalId);
      
      // 如果关闭的是当前选中的终端，切换到其他终端
      if (selectedTerminalId === terminalId) {
        const remainingTerminals = currentTerminals.filter(t => t.id !== terminalId);
        if (remainingTerminals.length > 0) {
          setSelectedTerminalId(remainingTerminals[0].id);
          setCurrentTab(0);
        } else {
          setSelectedTerminalId(null);
        }
      }

      addLog('info', `终端会话已关闭: ${terminalId}`, 'terminal');
      toast.success('终端已关闭');
    } catch (error) {
      const errorMsg = error instanceof Error ? error.message : String(error);
      addLog('error', `关闭终端失败: ${errorMsg}`, 'terminal');
      console.error('Failed to close terminal:', error);
      toast.error('关闭终端失败: ' + (error as Error).message);
    }
  }, [selectedTerminalId, currentTerminals, removeTerminal, setSelectedTerminalId, addLog]);

  // 初始化终端实例
  const initializeTerminal = useCallback((terminalId: string, container: HTMLDivElement) => {
    if (terminalRefs.current.has(terminalId)) {
      return terminalRefs.current.get(terminalId)!;
    }

    const terminalConfig = config?.terminal_defaults || {
      font_family: 'SF Mono, Monaco, Consolas, monospace',
      font_size: 14,
      cursor_style: 'block',
      cursor_blink: true,
      scrollback: 10000,
      bell_sound: false,
    };

    const terminal = new XTerm({
      fontFamily: terminalConfig.font_family,
      fontSize: terminalConfig.font_size,
      cursorStyle: terminalConfig.cursor_style as any,
      cursorBlink: terminalConfig.cursor_blink,
      scrollback: terminalConfig.scrollback,

      theme: {
        background: '#1a1a1a',
        foreground: '#ffffff',
        cursor: '#ffffff',
        black: '#000000',
        red: '#e06c75',
        green: '#98c379',
        yellow: '#d19a66',
        blue: '#61afef',
        magenta: '#c678dd',
        cyan: '#56b6c2',
        white: '#ffffff',
        brightBlack: '#5c6370',
        brightRed: '#e06c75',
        brightGreen: '#98c379',
        brightYellow: '#d19a66',
        brightBlue: '#61afef',
        brightMagenta: '#c678dd',
        brightCyan: '#56b6c2',
        brightWhite: '#ffffff',
      },
    });

    // 添加插件
    const fitAddon = new FitAddon();
    const webLinksAddon = new WebLinksAddon();
    const searchAddon = new SearchAddon();

    terminal.loadAddon(fitAddon);
    terminal.loadAddon(webLinksAddon);
    terminal.loadAddon(searchAddon);

    // 打开终端
    terminal.open(container);
    fitAddon.fit();

    // 处理用户输入
    terminal.onData((data) => {
      // 记录用户输入（不记录特殊字符如回车、退格等）
      if (data.length === 1 && data.charCodeAt(0) >= 32 && data.charCodeAt(0) <= 126) {
        addLog('debug', `用户输入: ${data}`, 'terminal');
      } else if (data === '\r') {
        addLog('debug', '用户按下回车键', 'terminal');
      }
      
      // 发送输入到后端
      invoke('terminal_input', {
        terminalId,
        data,
      }).catch((error) => {
        const errorMsg = error instanceof Error ? error.message : String(error);
        addLog('error', `发送终端输入失败: ${errorMsg}`, 'terminal');
        console.error('Failed to send terminal input:', error);
      });
    });

    // 处理终端大小变化
    terminal.onResize(({ cols, rows }) => {
      invoke('terminal_resize', {
        terminalId,
        size: { cols, rows },
      }).catch((error) => {
        console.error('Failed to resize terminal:', error);
      });

      updateTerminal(terminalId, {
        size: { cols, rows },
      });
    });

    // 保存引用
    terminalRefs.current.set(terminalId, terminal);
    fitAddonRefs.current.set(terminalId, fitAddon);
    terminalContainerRefs.current.set(terminalId, container);

    return terminal;
  }, [config?.terminal_defaults, updateTerminal]);

  // 监听终端输出事件
  useEffect(() => {
    const unlistenOutput = listen<TerminalEvent>('terminal-output', (event) => {
      const { payload } = event;
      const terminal = terminalRefs.current.get(payload.terminal_id);
      
      if (terminal && payload.type === 'data') {
        terminal.write(payload.data);
      }
    });

    const unlistenLog = listen('terminal-log', (event: any) => {
      const { level, message, source, terminal_id } = event.payload;
      addLog(level as 'info' | 'warn' | 'error' | 'debug', message, source || 'system');
    });

    return () => {
      unlistenOutput.then(fn => fn());
      unlistenLog.then(fn => fn());
    };
  }, [addLog]);

  // 处理窗口大小变化
  useEffect(() => {
    const handleResize = () => {
      fitAddonRefs.current.forEach((fitAddon) => {
        try {
          fitAddon.fit();
        } catch (error) {
          console.warn('Failed to fit terminal:', error);
        }
      });
    };

    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  // 如果没有连接ID，显示选择连接界面
  if (!connectionId) {
    return (
      <Box sx={{ p: 3, textAlign: 'center' }}>
        <Typography variant="h5" gutterBottom>
          选择一个连接来打开终端
        </Typography>
        <Typography variant="body2" color="text.secondary" sx={{ mb: 3 }}>
          请先在连接管理页面建立SSH连接
        </Typography>
        <Button
          variant="contained"
          onClick={() => navigate('/connections')}
        >
          前往连接管理
        </Button>
      </Box>
    );
  }

  // 如果连接不存在
  if (!currentConnection) {
    return (
      <Box sx={{ p: 3, textAlign: 'center' }}>
        <Alert severity="error">
          连接不存在或已被删除
        </Alert>
        <Button
          variant="contained"
          onClick={() => navigate('/connections')}
          sx={{ mt: 2 }}
        >
          返回连接管理
        </Button>
      </Box>
    );
  }

  // 如果连接未建立
  if (!activeConnection || activeConnection.status.status !== 'connected') {
    return (
      <Box sx={{ p: 3, textAlign: 'center' }}>
        <Alert severity="warning">
          连接 "{currentConnection.name}" 未建立，请先连接服务器
        </Alert>
        <Button
          variant="contained"
          onClick={() => navigate('/connections')}
          sx={{ mt: 2 }}
        >
          前往连接管理
        </Button>
      </Box>
    );
  }

  return (
    <Box
      sx={{
        height: '100%',
        display: 'flex',
        flexDirection: 'column',
        position: isFullscreen ? 'fixed' : 'relative',
        top: isFullscreen ? 0 : 'auto',
        left: isFullscreen ? 0 : 'auto',
        right: isFullscreen ? 0 : 'auto',
        bottom: isFullscreen ? 0 : 'auto',
        zIndex: isFullscreen ? 9999 : 'auto',
        backgroundColor: isFullscreen ? 'background.default' : 'transparent',
      }}
    >
      {/* 终端头部 */}
      <Paper
        sx={{
          borderRadius: isFullscreen ? 0 : 1,
          borderBottomLeftRadius: 0,
          borderBottomRightRadius: 0,
        }}
      >
        <Box sx={{ display: 'flex', alignItems: 'center', px: 2, py: 1 }}>
          <Typography variant="subtitle1" sx={{ flexGrow: 1 }}>
            {currentConnection.name} - 终端
          </Typography>
          
          <Box sx={{ display: 'flex', gap: 1 }}>
            <Tooltip title="新建终端">
              <IconButton
                size="small"
                onClick={() => createTerminal(connectionId)}
                disabled={isLoading}
              >
                {isLoading ? <CircularProgress size={16} /> : <AddIcon />}
              </IconButton>
            </Tooltip>
            
            <Tooltip title={logPanelOpen ? "隐藏日志" : "显示日志"}>
              <IconButton 
                onClick={() => setLogPanelOpen(!logPanelOpen)}
                size="small"
                color={logPanelOpen ? "primary" : "default"}
              >
                <ViewSidebarIcon />
              </IconButton>
            </Tooltip>
            
            <Tooltip title={isFullscreen ? '退出全屏' : '全屏'}>
              <IconButton
                size="small"
                onClick={() => setIsFullscreen(!isFullscreen)}
              >
                {isFullscreen ? <FullscreenExitIcon /> : <FullscreenIcon />}
              </IconButton>
            </Tooltip>
            
            <Tooltip title="设置">
              <IconButton size="small">
                <SettingsIcon />
              </IconButton>
            </Tooltip>
          </Box>
        </Box>

        {/* 终端标签 */}
        {currentTerminals.length > 0 && (
          <Tabs
            value={currentTab}
            onChange={(_, newValue) => setCurrentTab(newValue)}
            variant="scrollable"
            scrollButtons="auto"
            sx={{ borderTop: 1, borderColor: 'divider' }}
          >
            {currentTerminals.map((terminal) => (
              <Tab
                key={terminal.id}
                label={
                  <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
                    <span>{terminal.title}</span>
                    <IconButton
                      size="small"
                      onClick={(e) => {
                        e.stopPropagation();
                        closeTerminal(terminal.id);
                      }}
                      sx={{ ml: 1, p: 0.25 }}
                    >
                      <CloseIcon fontSize="small" />
                    </IconButton>
                  </Box>
                }
                sx={{ minHeight: 48 }}
              />
            ))}
          </Tabs>
        )}
      </Paper>

      {/* 终端内容区域 */}
      <Box sx={{ flex: 1, display: 'flex', overflow: 'hidden' }}>
        {/* 主终端区域 */}
        <Box sx={{ 
          flex: logPanelOpen ? '1 1 70%' : '1 1 100%', 
          display: 'flex', 
          flexDirection: 'column', 
          overflow: 'hidden',
          transition: 'flex 0.3s ease'
        }}>
          {currentTerminals.length === 0 ? (
            <Box
              sx={{
                height: '100%',
                display: 'flex',
                flexDirection: 'column',
                alignItems: 'center',
                justifyContent: 'center',
                backgroundColor: '#1a1a1a',
                color: 'white',
              }}
            >
              <Typography variant="h6" gutterBottom>
                还没有终端会话
              </Typography>
              <Typography variant="body2" color="text.secondary" sx={{ mb: 2 }}>
                点击上方的 + 按钮创建新的终端会话
              </Typography>
              <Button
                variant="contained"
                startIcon={<AddIcon />}
                onClick={() => createTerminal(connectionId)}
                disabled={isLoading}
              >
                创建终端
              </Button>
            </Box>
          ) : (
            currentTerminals.map((terminal, index) => (
              <TabPanel key={terminal.id} value={currentTab} index={index}>
                <Box
                  sx={{
                    height: '100%',
                    backgroundColor: '#1a1a1a',
                    position: 'relative',
                  }}
                  onContextMenu={(e) => {
                    e.preventDefault();
                    setContextMenu({
                      mouseX: e.clientX - 2,
                      mouseY: e.clientY - 4,
                    });
                  }}
                >
                  <div
                    ref={(el) => {
                      if (el && !terminalContainerRefs.current.has(terminal.id)) {
                        initializeTerminal(terminal.id, el);
                      }
                    }}
                    style={{
                      width: '100%',
                      height: '100%',
                      padding: '8px',
                    }}
                  />
                </Box>
              </TabPanel>
            ))
          )}
        </Box>

        {/* 日志面板 */}
        {logPanelOpen && (
          <Paper
            sx={{
              flex: '0 0 30%',
              display: 'flex',
              flexDirection: 'column',
              borderLeft: 1,
              borderColor: 'divider',
              backgroundColor: 'background.paper',
            }}
          >
            {/* 日志面板标题栏 */}
            <Box
              sx={{
                p: 1,
                borderBottom: 1,
                borderColor: 'divider',
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'space-between',
                backgroundColor: 'background.default',
              }}
            >
              <Typography variant="subtitle2" sx={{ fontWeight: 600 }}>
                连接日志
              </Typography>
              <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
                <FormControlLabel
                  control={
                    <Switch
                      size="small"
                      checked={autoScroll}
                      onChange={(e) => setAutoScroll(e.target.checked)}
                    />
                  }
                  label="自动滚动"
                  sx={{ mr: 1, '& .MuiFormControlLabel-label': { fontSize: '0.75rem' } }}
                />
                <Tooltip title="清空日志">
                  <IconButton size="small" onClick={clearLogs}>
                    <ClearIcon fontSize="small" />
                  </IconButton>
                </Tooltip>
                <Tooltip title="关闭日志面板">
                  <IconButton size="small" onClick={() => setLogPanelOpen(false)}>
                    <CloseIcon fontSize="small" />
                  </IconButton>
                </Tooltip>
              </Box>
            </Box>

            {/* 日志内容 */}
            <Box
              ref={logContainerRef}
              sx={{
                flex: 1,
                overflow: 'auto',
                p: 1,
                fontSize: '0.75rem',
                fontFamily: 'monospace',
                backgroundColor: '#fafafa',
              }}
            >
              {logs.length === 0 ? (
                <Typography
                  variant="body2"
                  color="text.secondary"
                  sx={{ textAlign: 'center', mt: 2 }}
                >
                  暂无日志
                </Typography>
              ) : (
                logs.map((log) => (
                  <Box
                    key={log.id}
                    sx={{
                      mb: 0.5,
                      p: 0.5,
                      borderRadius: 0.5,
                      backgroundColor: log.level === 'error' ? '#ffebee' : 
                                     log.level === 'warn' ? '#fff3e0' : 
                                     log.level === 'info' ? '#e3f2fd' : 'transparent',
                    }}
                  >
                    <Box sx={{ display: 'flex', alignItems: 'flex-start', gap: 1 }}>
                      <Typography
                        component="span"
                        sx={{
                          fontSize: '0.7rem',
                          color: 'text.secondary',
                          minWidth: '60px',
                          flexShrink: 0,
                        }}
                      >
                        {formatLogTime(log.timestamp)}
                      </Typography>
                      <Typography
                        component="span"
                        sx={{
                          fontSize: '0.7rem',
                          color: getLogLevelColor(log.level),
                          fontWeight: 600,
                          minWidth: '45px',
                          flexShrink: 0,
                          textTransform: 'uppercase',
                        }}
                      >
                        {log.level}
                      </Typography>
                      <Typography
                        component="span"
                        sx={{
                          fontSize: '0.7rem',
                          color: 'text.secondary',
                          minWidth: '60px',
                          flexShrink: 0,
                        }}
                      >
                        [{log.source}]
                      </Typography>
                      <Typography
                        component="span"
                        sx={{
                          fontSize: '0.7rem',
                          color: 'text.primary',
                          wordBreak: 'break-word',
                          flex: 1,
                        }}
                      >
                        {log.message}
                      </Typography>
                    </Box>
                  </Box>
                ))
              )}
            </Box>
          </Paper>
        )}
      </Box>

      {/* 右键菜单 */}
      <Menu
        open={contextMenu !== null}
        onClose={() => setContextMenu(null)}
        anchorReference="anchorPosition"
        anchorPosition={
          contextMenu !== null
            ? { top: contextMenu.mouseY, left: contextMenu.mouseX }
            : undefined
        }
      >
        <MenuItem
          onClick={() => {
            // 复制选中文本
            const terminal = terminalRefs.current.get(currentTerminals[currentTab]?.id);
            if (terminal && terminal.hasSelection()) {
              const selection = terminal.getSelection();
              navigator.clipboard.writeText(selection);
              toast.success('已复制到剪贴板');
            }
            setContextMenu(null);
          }}
        >
          <CopyIcon sx={{ mr: 1 }} />
          复制
        </MenuItem>
        <MenuItem
          onClick={async () => {
            // 粘贴剪贴板内容
            try {
              const text = await navigator.clipboard.readText();
              const terminal = terminalRefs.current.get(currentTerminals[currentTab]?.id);
              if (terminal) {
                terminal.paste(text);
              }
            } catch (error) {
              toast.error('粘贴失败');
            }
            setContextMenu(null);
          }}
        >
          <PasteIcon sx={{ mr: 1 }} />
          粘贴
        </MenuItem>
        <MenuItem
          onClick={() => {
            // 清屏
            const terminal = terminalRefs.current.get(currentTerminals[currentTab]?.id);
            if (terminal) {
              terminal.clear();
            }
            setContextMenu(null);
          }}
        >
          <RefreshIcon sx={{ mr: 1 }} />
          清屏
        </MenuItem>
      </Menu>
    </Box>
  );
};

export default Terminal;